package net.proef.sample.aspect;

import java.util.Collection;
import java.util.List;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

@Aspect
public class SimpleProfilingAspect {
	private Logger logger = LoggerFactory
			.getLogger(SimpleProfilingAspect.class);

	private Multimap<String, Long> timings = ArrayListMultimap.create();

	@Pointcut("execution(public java.util.List net.proef.sample.service.BookService.get*(..))")
	public void publicGetMethods() {
	}

	@Around("publicGetMethods()")
	public Object traceAround(ProceedingJoinPoint pjp) throws Throwable {
		long end, start = System.nanoTime();
		List<?> result = null;

		try {
			result = (List<?>) pjp.proceed();
		} catch (Throwable e) {
			// rethrow to not interrup normal program flow
			throw e;
		} finally {
			end = System.nanoTime();

			timings.put(pjp.toLongString(), (end - start));
			Collection<Long> values = timings.get(pjp.toLongString());

			Long sum = 0L;
			for (Long value : values) {
				sum += value;
			}

			logger.trace("AroundAdvice '{}' duration={}ns, average={}ns",
					new Object[] { pjp.getSignature(), (end - start),
							(sum / values.size()) });
		}

		return result;
	}
}
